#pragma once  
#include <vector>
#include "../../DataStructsDef.h"
#include "..\\UtilDefs.h"
#include "..\\..\\Effects11\\Inc\\d3dx11effect.h"
#include "..\\DirectoryUtil.h"
#include "..\\..\\IO\\Material.h"
#include "RenderableTexture2D.hpp"
#include "../../IO/XYZFileIO.h"
#include "../UtilityString.h"
#include "../HiPerfTimer.h"

class CD3DUtilityFunction
{
public:
	CD3DUtilityFunction(void);
	~CD3DUtilityFunction(void);
	static HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut );	
	static HRESULT FillVec3(float x, float y, float z, D3DXVECTOR3* pDst);
	static HRESULT CreateVBVec3(ID3D11Device* pd3dDevice, int iDataWidth, int iDataHeight, float fWidthLength, float fHeightLength, 
		                        float fStartOffsetX, float fStartOffsetY, float* pSrcDataBuf, ID3D11Buffer** ppVB);
	static HRESULT CreateIBGrid32Bit(ID3D11Device* pd3dDevice, int iDataWidth, int iDataHeight, ID3D11Buffer** ppIB);
	static HRESULT CreateVertexBuffer(ID3D11Device* pd3dDevice, int iStride, float* pSrcDataBuf, int iNumVertices, ID3D11Buffer** ppVB);
	static HRESULT CreateIndexBuffer(ID3D11Device* pd3dDevice, int iNumofIndices, void* pIndicesBuf, ID3D11Buffer** ppIB, bool b32Bit = true);
	static HRESULT CreateEffectsFromFile(ID3D11Device* pd3dDevice, WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DX11Effect** ppEffect );
	static HRESULT CreateVertexLayout(ID3D11Device* pd3dDevice, const D3D11_INPUT_ELEMENT_DESC layout[], int numElems, ID3DX11EffectTechnique* pTech, ID3D11InputLayout** ppLayout11);
	static D3DXMATRIX LerpMatrix(D3DXMATRIX& a, D3DXMATRIX& b, float s);
	static void CreateFileName(char pFileName[], unsigned int iSize, CDirectoryUtil* pDirUtil, enum SUBDIRECTORY iSubFolder, TCHAR* sFileName);
	static HRESULT CreateD3D9Device(IDirect3DDevice9** ppd3dDevice);
	static void InitMaterial( Material* pMaterial );
	static float ComputeTriangleArea(const D3DXVECTOR3& v1, const D3DXVECTOR3& v2, const D3DXVECTOR3& v3);
	static void ComputeTriangleNormal(D3DXVECTOR3& vNorm, const D3DXVECTOR3& v1, const D3DXVECTOR3& v2, const D3DXVECTOR3& v3);
	static D3DXVECTOR3 GetColour(float v,float vmin,float vmax);
	static HRESULT SaveNDFFloatImageData(ID3D11Device* pd3dDevice, const wchar_t* sFileName, unsigned int iWidth, unsigned int iHeight, 
								std::vector<double>& arrNDFCumulate, float fNormalizeFactor = 1.0f);
	static HRESULT SaveNDFImage(ID3D11Device* pd3dDevice, const wchar_t* sFileName, unsigned int iWidth, unsigned int iHeight, 
								std::vector<double>& arrNDFCumulate, float fNormalizeFactor = 1.0f);
	static HRESULT SaveNDFImage_Gray(ID3D11Device* pd3dDevice, const wchar_t* sFileName, unsigned int iWidth, unsigned int iHeight, 
		std::vector<double>& arrNDFCumulate, float fNormalizeFactor = 1.0f);
	static HRESULT GenDiffOfTowTextures(ID3D11Device* pd3dDevice, const wchar_t* sFileTex1, const wchar_t* sFileTex2, 
										const wchar_t* sFileOutput, DXGI_FORMAT fmtLoadTex);
	static bool Save1DPlotData(char* str1DPlotFile, D3DXVECTOR3* pNormalData, unsigned int iNumNormal, bool bWhichAxis);
	static HRESULT SaveFrameBufferToFile( ID3D11DeviceContext *pContext, WCHAR* sFileName,  enum D3DX11_IMAGE_FILE_FORMAT format);
	static HRESULT CreateScreenQuadVB(ID3D11Device* pd3dDevice, ID3D11Buffer** ppQuadVB);
	static float ComputeFresnelTermUsingSchlick(float fRefractiveIndex, const D3DXVECTOR3& vInVec, const D3DXVECTOR3& vHalfVec);
	//debug function
	static void PrintD3DXMatrix(const D3DXMATRIX& pMat);
	//Create Assistance Shapes
	//--------------------------------------------------------------------------------------
	static inline void sincosf( float angle, float* psin, float* pcos )
	{
		*psin = sinf( angle );
		*pcos = cosf( angle );
	}
	static HRESULT CreateShapeMesh(ID3D11Device* pDevice, ID3D11Buffer** ppVB, VertexType_POSNORM* pVertices, unsigned int iNumVertices, ID3D11Buffer** ppIB,  WORD* pwIndices, unsigned int iNumIndices);
	static void MakeSphere( VertexType_POSNORM* pVertices, WORD* pwIndices, float fRadius, UINT uSlices, UINT uStacks );
	static HRESULT CreateAssistSphere(ID3D11Device* pDevice, float fRadius, UINT uSlices, UINT uStacks, ID3D11Buffer** ppVB, ID3D11Buffer** ppIB, unsigned int* piNumVertices, unsigned int* piNumIndices );
	static void MakeTeapot(VertexType_POSNORM* pVertices, WORD* pwIndices);
	static HRESULT CreateAssistTeapot( ID3D11Device* pDevice, ID3D11Buffer** ppVB, ID3D11Buffer** ppIB,  unsigned int* piNumVertices, unsigned int* piNumIndices  );
	static void ComputeIntersectionBtwLineAnd2DGrids( std::vector<CPoint>& arrIntersectPts, D3DXVECTOR2 startPt, D3DXVECTOR2 endPt, unsigned int left = 0, unsigned int top = 0, unsigned int right = 511, unsigned int bottom = 511);
	static float Convert2DPosToAngle(int xpos, int ypos, int iDimX, int iDimY, NDFGENDIR iWhichDir);
	static void Convert2DPosTo2Angles(int xpos, int ypos, int iDimX, int iDimY, float& fThetaM, float& fPhiM);
	static int Compute2DUniformGaussianKernel(double fSigma, double fPixelStep, std::vector<double>& arrGaussCoeffs);
	static double EvalAnisotropicGGX(double fThetaM, double fPhiM, double a_x, double a_y, double b = 1.0);
	static double EvalAnisotropicBeckmann(double fThetaM, double fPhiM, double a_x, double a_y, double b = 1.0);
	static double computeFresnelComplex(double iorIncidentReal, double iorTransmittedReal, double iorTransmittedImaginary, double cosIncident);

	static float Ang2Rad(float fAng){ return D3DX_PI*(fAng/180);}
	//angle in degrees
	static void vecFromThetaPhi(D3DXVECTOR3& vec, float fTheta, float fPhi);
	//angle in radians
	static void vecFromThetaPhi_Rad(D3DXVECTOR3& vec, float fTheta, float fPhi);

	//z-order hashing value generation!
	//http://en.wikipedia.org/wiki/Z-order_curve
	//http://www.igorkromin.net/?x=entry:entry130312-153637
	static unsigned int coordToZOrderHash_2D(unsigned int iCoordX, unsigned int iCoordY);

    //fill 2d heightmap with ellipsoid equation
	static void fill2DHMWithEllipsoidEq(const double a_x, const double a_y, const double fRadiusX, const double fRadiusY, const unsigned int i2dDimX, 
		const unsigned int i2dDimY, std::vector<VertexNorm>& arrHMVertices , double fScaleFactor = 1.0 );
	static void fill2DHMWithSinCosWave(const int iNumWaves, const unsigned int i2dDimX, const unsigned int i2dDimY, const double fStartOffsetX, 
		const double fStartOffsetY, const double fRadiusX, const double fRadiusY, std::vector<VertexNorm>& arrHMVertices, 
		bool bAlongAxisY = true, bool bSin = true);

	static void fill2DHMWithSinCosWave_Irregular(const int iNumWaves, const unsigned int iWhichValley_Irregular, const float fScaleRatio, const unsigned int i2dDimX, const unsigned int i2dDimY, const double fStartOffsetX, 
		const double fStartOffsetY, const double fRadiusX, const double fRadiusY, std::vector<VertexNorm>& arrHMVertices, 
		bool bAlongAxisY = true, bool bSin = true);

	static void fill2DHMWithAFM1DSlice(const std::vector<UtilityString>& arrAFM1DSlicesFN, CXYZFileIO* pXYZFile);

	static void comp2DLineSegIntersection(const double& ptStart_x_L1, const double& ptStart_y_L1, const double& ptEnd_x_L1, const double& ptEnd_y_L1, 
		const double& ptStart_x_L2, const double& ptStart_y_L2, const double& ptEnd_x_L2, const double& ptEnd_y_L2, 
		double& u, double &v
		);
	static void raytrace1DSlicein2D(const CGrowableArray<Ray2D>& arrInitRays, const CGrowableArray<LineSeg2D>& arr1DLineSegs, FILE* fp_output);
	static bool checkLineIntersectBox2D(const double box_x_min, const double box_x_max, const double box_y_min, 
		const double box_y_max, Ray2D& InputRay);
};

